package uk.co.douglashoskins.weathercompare.providers;

import java.io.DataInputStream;
import java.io.IOException;
import java.util.Vector;

import javax.microedition.lcdui.Image;

import org.json.me.JSONArray;
import org.json.me.JSONException;
import org.json.me.JSONObject;

import uk.co.douglashoskins.weathercompare.Assets;
import uk.co.douglashoskins.weathercompare.WeatherCompare;
import uk.co.douglashoskins.weathercompare.controller.WeatherController;
import uk.co.douglashoskins.weathercompare.controller.WeatherObj;
import uk.co.douglashoskins.weathercompare.controller.WeatherObj.WeatherSummary;
import uk.co.douglashoskins.weathercompare.services.NetQueueCallback;
import uk.co.douglashoskins.weathercompare.util.Weather;

public class BBC implements NetQueueCallback, WeatherProvider {
	private WeatherCallback wc;
	private Vector entries = null;
	
	private void readEntries() throws IOException {
		DataInputStream dis = new DataInputStream(this.getClass().getResourceAsStream("res/data/bbc.txt"));
		entries = new Vector();
		int count = dis.readInt();
		for (int i=0; i<count; i++) {
			entries.addElement(new BBCEntry(dis.readUTF(), dis.readDouble(), dis.readDouble(), dis.readUTF()));
		}
	}
	
	public BBCEntry closest(double lat, double lng) throws IOException {
		if (entries == null) {
			readEntries();
		}
		BBCEntry closest = null;
		double minDist = Double.MAX_VALUE;
		int numEntries = entries.size();
		for (int i=0; i<numEntries; i++) {
			BBCEntry entry = (BBCEntry) entries.elementAt(i);
			double dist = Weather.haversine(lat, lng, entry.lat, entry.lng);
			if (dist < minDist) {
				minDist = dist;
				closest = entry;
			}
		}
		return closest;
	}
	
	public void getWeather(double lat, double lng, WeatherCallback wc) {
		this.wc = wc;
		try {
			BBCEntry closest = closest(lat, lng);
			
			String yql = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%20%3D%20%22http%3A%2F%2Fnewsrss.bbc.co.uk%2Fweather%2Fforecast%2F" + closest.code + "%2FNext3DaysRSS.xml%22&format=json";
			
			WeatherCompare.n.addRequest(yql, this);
		} catch (IOException e) {}
		
	}
	
	private int readTemp(String str, int start) {
		String temp = "";
		int i = start;
		char ch;
		for (;;) {
			ch = str.charAt(i++);
			if (ch == '-' || (ch >= '0' && ch <= '9')) {
				temp += ch;
			} else {
				break;
			}
		}
		return Integer.parseInt(temp);
	}
	
	private int getCode(String condition) {
		condition = condition.toLowerCase();
		if (condition.indexOf("storm") != -1) {
			return Weather.THUNDERSTORM;
		}
		if (condition.indexOf("snow") != -1 || condition.indexOf("sleet") != -1) {
			return Weather.SNOW;
		}
		if (condition.indexOf("intervals") != -1) {
			return Weather.SUNNY_INTERVALS;
		}
		if (condition.indexOf("showers") != -1 || condition.indexOf("rain") != -1) {
			return Weather.RAIN;
		}
		if (condition.indexOf("fog") != -1 || condition.indexOf("mist") != -1) {
			return Weather.FOG;
		}
		if (condition.indexOf("sun") != -1 || condition.indexOf("clear") != -1) {
			return Weather.SUN;
		}
		return Weather.CLOUD;
	}
	
	private void populateWeatherObject(JSONObject day, WeatherSummary ws) throws JSONException {
		String title = day.getString("title");
		int colon = title.indexOf(':');
		int comma = title.indexOf(',', colon);
		ws.text = title.substring(colon + 1, comma);
		title = title.toLowerCase();
		int maxTempStart = title.indexOf("max temp");
		maxTempStart += 10;
		ws.high = readTemp(title, maxTempStart);
		int minTempStart = title.indexOf("min temp");
		minTempStart += 10;
		ws.low = readTemp(title, minTempStart);
		ws.code = getCode(title);
	}

	public void netCallback(String s) throws IOException {
		try {
			JSONObject j = new JSONObject(s);
			JSONObject results = j.getJSONObject("query").getJSONObject("results");
			JSONArray items = results.getJSONObject("rss").getJSONObject("channel").getJSONArray("item");
			JSONObject today = items.getJSONObject(0);
			JSONObject tomorrow = items.getJSONObject(1);
			WeatherObj wo = new WeatherObj();
			populateWeatherObject(today, wo.today);
			populateWeatherObject(tomorrow, wo.tomorrow);
			wc.weatherCB(wo, this);
		} catch (JSONException e) {
			wc.weatherErr(this);
		} 
	}

	public void netException(Exception exc) {
		wc.weatherErr(this);
	}

	public Image logo() {
		return Assets.BBC;
	}

	public String name() { return "BBC"; }
}
